#ifndef ___ejecutar_comando

#define ___ejecutar_comando 1

#include "pd_pcoms.c"
#include "mtlib.c"
#include <stdlib.h>

unsigned char ejecutarComando(comando_t);
unsigned int obtenerConexion(void);
long sectorAleatorio(void);
unsigned long aleatorio(unsigned long);

unsigned char ejecutarComando (comando_t comando) {
  unsigned int conexion;
  sectores_t sectores;
  switch (comando.tipo) {
  case 0:
    printf("Cuarenta y seis.\n");
    return *estado;
  case 1:
    if (cantConexiones) {
      printf("Las conexiones ya existen.\n");
      return *estado;
    }
    cantConexiones = comando.datos.abrir.cantidad;
    printf("Conectando %d conexiones...\n", cantConexiones);
    conexiones = malloc(sizeof(unsigned int) * cantConexiones);
    mti_direccion_ipv4 direccion;
    direccion.elem0 = comando.datos.abrir.elem0;
    direccion.elem1 = comando.datos.abrir.elem1;
    direccion.elem2 = comando.datos.abrir.elem2;
    direccion.elem3 = comando.datos.abrir.elem3;
    int puerto = comando.datos.abrir.puerto;
    unsigned int posicion;
    for (posicion = 0; posicion < cantConexiones; posicion ++) {
      conexiones[posicion] = mtf_conectar(centroMensajes, MTP_IPV4, direccion, puerto);
      mtf_enviar_handshake(centroMensajes, conexiones[posicion], 0, NULL);
    }
    printf("Conectadas todas las conexiones.\n");
    return *estado + 1;
  case 2:
    printf("Cerrando todo...\n");
    return 0;
  case 3:
    if (cantidadSectores) {
      printf("La cantidad de sectores ya fue configurada.\n");
      return *estado;
    }
    cantidadSectores = comando.datos.sectoresDisco;
    printf("Configurado disco de %u sectores.\n", cantidadSectores);
    return *estado + 1;
  case 4:
    if (!cantConexiones) {
      printf("No esta conectado.\n");
      return *estado;
    }
    if (comando.datos.conexion > (int) cantConexiones) {
      printf("Conexion %d no existe.\n", comando.datos.conexion);
      return *estado;
    }
    conexionActiva = comando.datos.conexion;
    if (conexionActiva == -1)
      printf("Configurada conexion aleatoria.\n");
    else
      printf("Configurada conexion numero %d.\n", conexionActiva);
    return *estado;
  case 5:
    if (*estado < 3) {
      printf("No esta completamente configurado.\n");
      return *estado;
    }
    conexion = obtenerConexion();
    printf("Enviando mensajes de lectura...\n");
    sectores = comando.datos.sectoresLeer;
    if (sectores.tipo == 1)
      mtf_enviar_mensaje(centroMensajes, conexion, MTE_LEER_SECTOR, (long) sectores.valores.sector);
    else if (sectores.tipo == 2) {
      long sector, tope;
      sector = sectores.valores.rango.inicio;
      tope = sectores.valores.rango.fin;
      if (sector > tope) {
        long aux = tope;
        tope = sector;
        sector = aux;
      }
      for (; sector <= tope; sector ++)
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_LEER_SECTOR, sector);
    } else if (sectores.tipo == 3) {
      unsigned long cantidad = sectores.valores.cantidad;
      long sector;
      for (; cantidad; cantidad --) {
        sector = sectorAleatorio();
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_LEER_SECTOR, sector);
      }
    } else if (sectores.tipo == 4) {
      unsigned int posicion;
      for (posicion = 0; posicion < sectores.valores.lista.cantidad; posicion ++)
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_LEER_SECTOR, (long) sectores.valores.lista.numeros[posicion]);
      free(sectores.valores.lista.numeros);
    } else {
      long sector;
      for (sector = 0; sector < cantidadSectores; sector ++)
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_LEER_SECTOR, sector);
    }
    printf("Mensajes enviados.\n");
    return *estado;
  case 6:
  if (*estado < 3) {
      printf("No esta completamente configurado.\n");
      return *estado;
    }
    conexion = obtenerConexion();
    printf("Enviando mensajes de escritura...\n");
    sectores = comando.datos.escribir.sectores;
    void * datos = comando.datos.escribir.bytes;
    if (sectores.tipo == 1)
      mtf_enviar_mensaje(centroMensajes, conexion, MTE_ESCRIBIR_SECTOR, (long) sectores.valores.sector, datos);
    else if (sectores.tipo == 2) {
      long sector, tope;
      sector = sectores.valores.rango.inicio;
      tope = sectores.valores.rango.fin;
      if (sector > tope) {
        long aux = tope;
        tope = sector;
        sector = aux;
      }
      for (; sector <= tope; sector ++)
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_ESCRIBIR_SECTOR, sector, datos);
    } else if (sectores.tipo == 3) {
      unsigned long cantidad = sectores.valores.cantidad;
      long sector;
      for (; cantidad; cantidad --) {
        sector = sectorAleatorio();
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_ESCRIBIR_SECTOR, sector, datos);
      }
    } else if (sectores.tipo == 4) {
      unsigned int posicion;
      for (posicion = 0; posicion < sectores.valores.lista.cantidad; posicion ++)
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_ESCRIBIR_SECTOR, (long) sectores.valores.lista.numeros[posicion], datos);
      free(sectores.valores.lista.numeros);
    } else {
      long sector;
      for (sector = 0; sector < cantidadSectores; sector ++)
        mtf_enviar_mensaje(centroMensajes, conexion, MTE_ESCRIBIR_SECTOR, sector, datos);
    }
    printf("Mensajes enviados.\n");
    return *estado;
  case 7:
    if (!cantConexiones) {
      printf("No esta conectado.\n");
      return *estado;
    }
    if (comando.datos.conexion == -1) {
      printf("Probando todas las conexiones...\n");
      int posicion;
      for (posicion = 0; posicion < cantConexiones; posicion ++)
        mtf_enviar_mensaje(centroMensajes, conexiones[posicion], MTE_NULL);
      printf("Enviados todos los mensajes de prueba.\n");
      return *estado;
    }
    if (comando.datos.conexion > cantConexiones) {
      printf("Conexion %d no existe.\n", comando.datos.conexion);
      return *estado;
    }
    printf("Probando conexion %d...\n", comando.datos.conexion);
    mtf_enviar_mensaje(centroMensajes, conexiones[comando.datos.conexion - 1], MTE_NULL);
    printf("Enviado mensaje de prueba.\n");
    return *estado;
  }
}

unsigned int obtenerConexion (void) {
  if (conexionActiva == -1)
    return conexiones[aleatorio(cantConexiones)];
  else
    return conexiones[conexionActiva - 1];
}

long sectorAleatorio (void) {
  return aleatorio(cantidadSectores);
}

unsigned long aleatorio (unsigned long maximo) {
  unsigned long n1, n2, n3, n4;
  n1 = rand() & 255;
  n2 = rand() & 255;
  n3 = rand() & 255;
  n4 = rand() & 255;
  n2 <<= 8;
  n3 <<= 16;
  n4 <<= 24;
  n1 |= n2;
  n3 |= n4;
  n1 |= n3;
  return n1 % maximo;
}

#endif